package com.skyjing.askit

import android.content.Context
import android.content.SharedPreferences
import androidx.collection.SimpleArrayMap
import com.skyjing.askit.AsTool.getApp
import java.util.*

object AsSpTool {
    private val SP_UTILS_MAP = SimpleArrayMap<String, SpUitls>()

    @JvmStatic
    fun init() {
        init(
            spName = "SpUitls",
            mode = Context.MODE_PRIVATE
        )
    }

    @JvmStatic
    fun init(mode: Int = Context.MODE_PRIVATE) {
        init(
            spName = "SpUitls",
            mode = Context.MODE_PRIVATE
        )
    }

    @JvmStatic
    fun init(spName: String = "SpUitls") {
        init(spName, mode = Context.MODE_PRIVATE)
    }

    @JvmStatic
    fun init(spName: String = "SpUitls", mode: Int = Context.MODE_PRIVATE) {
        var spName = spName
        if (isEmpty(spName)) spName = "SpUitls"
        var spUtils = SP_UTILS_MAP[spName]
        if (spUtils == null) {
            SP_UTILS_MAP.put(spName,
                SpUitls(spName, mode)
            )
        }
    }

    private fun isEmpty(s: String?): Boolean {
        if (s == null) return true
        var i = 0
        val len = s.length
        while (i < len) {
            if (!Character.isWhitespace(s[i])) {
                return false
            }
            ++i
        }
        return true
    }

    @JvmStatic
    fun put(tag : String = "SpUitls",key: String, value: Any?, isCommit: Boolean = false){
        var spUtils = SP_UTILS_MAP[tag]
        spUtils?.put(key , value , isCommit)
    }

    @JvmStatic
    fun put(tag : String = "SpUitls",key: String, value: Any?){
        put(tag, key, value, false)
    }

    @JvmStatic
    fun put(key: String, value: Any?){
        put("SpUitls", key, value)
    }


    @JvmStatic
    fun getString(key: String):String{
        return getString(key , defValue = "")
    }

    @JvmStatic
    fun getString(key: String , defValue: String = ""):String{
        return getString("SpUitls", key, defValue)
    }

    @JvmStatic
    fun getString(tag : String = "SpUitls",key: String, defValue: String = ""):String{
        var spUtils = SP_UTILS_MAP[tag]
        var temp = spUtils?.getString(key , defValue)
        if (temp != null) return temp
        else return ""
    }

    @JvmStatic
    fun getBoolean(key: String):Boolean{
        return getBoolean("SpUitls", key)
    }

    @JvmStatic
    fun getBoolean(key: String , defValue: Boolean = false):Boolean{
        return getBoolean(
            "SpUitls",
            key,
            defValue = false
        )
    }

    @JvmStatic
    fun getBoolean(tag : String = "SpUitls",key: String, defValue: Boolean = false):Boolean{
        var spUtils = SP_UTILS_MAP[tag]
        var temp = spUtils?.getBoolean(key , defValue)
        if (temp != null) return temp
        else return false
    }


    @JvmStatic
    fun getInt(key: String):Int{
        return getInt("SpUitls", key)
    }

    @JvmStatic
    fun getInt(key: String, defValue: Int = 0):Int{
        return getInt("SpUitls", key, defValue)
    }

    @JvmStatic
    fun getInt(tag : String = "SpUitls",key: String, defValue: Int = 0):Int{
        var spUtils = SP_UTILS_MAP[tag]
        var temp = spUtils?.getInt(key , defValue)
        if (temp != null) return temp
        else return  0
    }


    @JvmStatic
    fun getFloat(key: String):Float{
        return getFloat("SpUitls", key)
    }

    @JvmStatic
    fun getFloat(key: String,defValue: Float = 0f):Float{
        return getFloat("SpUitls", key, defValue)
    }

    @JvmStatic
    fun getFloat(tag : String = "SpUitls",key: String, defValue: Float = 0f):Float{
        var spUtils = SP_UTILS_MAP[tag]
        var temp = spUtils?.getFloat(key , defValue)
        if (temp != null) return temp
        else return 0f
    }


    @JvmStatic
    fun getLong(key: String):Long{
        return getLong("SpUitls", key)
    }

    @JvmStatic
    fun getLong(key: String, defValue: Long = 0):Long{
        return getLong("SpUitls", key, defValue = 0)
    }

    @JvmStatic
    fun getLong(tag : String = "SpUitls",key: String, defValue: Long = 0):Long{
        var spUtils = SP_UTILS_MAP[tag]
        var temp = spUtils?.getLong(key , defValue)
        if (temp != null) return temp
        else return 0
    }


    private class SpUitls {
        //    private static Context mContext;
//    private static final SimpleArrayMap<String, AsSpTools> SP_UTILS_MAP = new SimpleArrayMap<>();
        private var sp: SharedPreferences?

        //    public static AsSpTools getInstance(/*Context context,*/) {
//        return getInstance("", Context.MODE_PRIVATE);
//    }
//
//    public static AsSpTools getInstance(/*Context context,*/int mode) {
//        return getInstance( "", mode);
//    }
//
//    public static AsSpTools getInstance(/*Context context,*/ String spName) {
//        return getInstance(spName, Context.MODE_PRIVATE);
//    }
//
//    public static AsSpTools getInstance(/*Context context,*/ String spName, int mode) {
////        mContext = AsTools.getApp();
//        if (isEmpty(spName)) spName = "SpUitls";
//        AsSpTools spUtils = SP_UTILS_MAP.get(spName);
//        if (spUtils == null) {
//            spUtils = new AsSpTools(spName, mode);
//            SP_UTILS_MAP.put(spName, spUtils);
//        }
//        return spUtils;
//    }
        constructor(spName: String?) {
            sp = Objects.requireNonNull(getApp())
                ?.getSharedPreferences(spName, Context.MODE_PRIVATE)
        }

        constructor(spName: String?, mode: Int) {
            sp = Objects.requireNonNull(getApp())?.getSharedPreferences(spName, mode)
        }

        @JvmOverloads
        fun put(key: String, value: Any?, isCommit: Boolean = false) {
            if (isCommit) {
                if (value is String) {
                    sp!!.edit().putString(key, value as String?).commit()
                } else if (value is Long) {
                    sp!!.edit().putLong(key, (value as Long?)!!).commit()
                } else if (value is Boolean) {
                    sp!!.edit().putBoolean(key, (value as Boolean?)!!).commit()
                } else if (value is Float) {
                    sp!!.edit().putFloat(key, (value as Float?)!!).commit()
                } else if (value is Int) {
                    sp!!.edit().putInt(key, (value as Int?)!!).commit()
                } else {
                    sp!!.edit().putStringSet(key, value as Set<String?>?)
                        .commit()
                }
            } else {
                if (value is String) {
                    sp!!.edit().putString(key, value as String?).apply()
                } else if (value is Long) {
                    sp!!.edit().putLong(key, (value as Long?)!!).apply()
                } else if (value is Boolean) {
                    sp!!.edit().putBoolean(key, (value as Boolean?)!!).apply()
                } else if (value is Float) {
                    sp!!.edit().putFloat(key, (value as Float?)!!).apply()
                } else if (value is Int) {
                    sp!!.edit().putInt(key, (value as Int?)!!).apply()
                } else {
                    sp!!.edit().putStringSet(key, value as Set<String?>?)
                        .apply()
                }
            }
        }

        fun getString(key: String?): String? {
            return getString(key, "")
        }

        fun getString(key: String?, defValue: String?): String? {
            return sp!!.getString(key, defValue)
        }

        fun getBoolean(key: String?): Boolean {
            return getBoolean(key, false)
        }

        fun getBoolean(key: String?, defValue: Boolean): Boolean {
            return sp!!.getBoolean(key, defValue)
        }

        fun getInt(key: String?): Int {
            return getInt(key, 0)
        }

        fun getInt(key: String?, defValue: Int): Int {
            return sp!!.getInt(key, defValue)
        }

        fun getFloat(key: String?): Float {
            return getFloat(key, 0f)
        }

        fun getFloat(key: String?, defValue: Float): Float {
            var value = 0f
            if (sp != null) {
                value = sp!!.getFloat(key, defValue)
            }
            return value
        }

        fun getLong(key: String?): Long {
            return getLong(key, 0)
        }

        fun getLong(key: String?, defValue: Long): Long {
            var value: Long = 0
            if (sp != null) {
                value = sp!!.getLong(key, defValue)
            }
            return value
        }

        fun getStringSet(key: String): Set<String>? {
            return getStringSet(key, emptySet<String>())
        }

        fun getStringSet(
            key: String,
            defaultValue: Set<String?>?
        ): Set<String>? {
            return sp!!.getStringSet(key, defaultValue)
        }

        val aLl: Map<String, *>
            get() = sp!!.all

        operator fun contains(key: String): Boolean {
            return sp!!.contains(key)
        }

        @JvmOverloads
        fun remove(key: String, isCommit: Boolean = false) {
            if (isCommit) {
                sp!!.edit().remove(key).commit()
            } else {
                sp!!.edit().remove(key).apply()
            }
        }

        @JvmOverloads
        fun clear(isCommit: Boolean = false) {
            if (isCommit) {
                sp!!.edit().clear().commit()
            } else {
                sp!!.edit().clear().apply()
            }
        }

        companion object {
            private fun isEmpty(s: String?): Boolean {
                if (s == null) return true
                var i = 0
                val len = s.length
                while (i < len) {
                    if (!Character.isWhitespace(s[i])) {
                        return false
                    }
                    ++i
                }
                return true
            }
        }
    }

}
